#include "dri.h"
#include "ifs.h"
#include "fs.h"
#include <string.h>
#include "kromdisk.h"
#include "dbgio.h"
#include "kmm.h"

struct vfs_node *romfs_dir;

ifs_descriptor_t *romfs_ifs_desc;
dri_driver_descriptor_t *romfs_dri_desc;

uint32_t romfs_read(struct vfs_node *node ,uint8_t *buffer ,uint32_t offset ,uint32_t length,uint32_t fflags){
	ROMDISK_FILE_T *file = (ROMDISK_FILE_T *) node->inode;
	//dprintf("romfs_read 0x%x 0x%x 0x%x\n",offset,length,file->length);
	if (offset >= file->length)
		return 0;
	if ((offset + length) > file->length)
		length = file->length - offset;
	memcpy(buffer,(void *)(node->impl+offset),length);
	return length;
}

uint32_t romfs_write(struct vfs_node *node ,uint8_t *buffer ,uint32_t offset ,uint32_t length,uint32_t fflags){
	return 0;
}

struct vfs_node * romfs_mkstub(struct vfs_node *node,char *name,uint32_t mode){
	return 0;
}

void romfs_ocstub(struct vfs_node *node){
	return;
}
struct vfs_dir * romfs_readdir(struct vfs_node *node,uint32_t id){
	ROMDISK_HEADER_T *rd_dir = (ROMDISK_HEADER_T *) node->inode;
	ROMDISK_FILE_T *file = (ROMDISK_FILE_T *)(((uint32_t)rd_dir)+((uint32_t)rd_dir->file_list));
	for (uint32_t current = 0;current < rd_dir->file_count;current++){
		if (file == 0)
			return 0;
		if (current == id){
			struct vfs_dir *dirent = (struct vfs_dir *)kmalloc(sizeof(vfs_dir_t));
			dirent->inode = (uint32_t)file;
			strcpy(dirent->name,(char *)file->filename);
			return dirent;
		}
		file = (ROMDISK_FILE_T *)(((uint32_t)rd_dir)+((uint32_t)file->next));
	}
	return 0;
}
struct vfs_node * romfs_getfile(vfs_node_t *par,ROMDISK_FILE_T *file);
struct vfs_node * romfs_finddir(struct vfs_node *node,char *name){
	ROMDISK_HEADER_T *rd_dir = (ROMDISK_HEADER_T *) node->inode;
	ROMDISK_FILE_T *file = (ROMDISK_FILE_T *)(((uint32_t)rd_dir)+((uint32_t)rd_dir->file_list));
	//dprintf("romfs_finddir %s\n",name);
	for (uint32_t current = 0;current < rd_dir->file_count;current++){
		if (file == 0)
			return 0;
		if (strcmp((char *)file->filename,name) == 0)
			return romfs_getfile(node,file);
		file = (ROMDISK_FILE_T *)(((uint32_t)rd_dir)+((uint32_t)file->next));
	}
	return 0;
}

struct vfs_node * romfs_getfile(vfs_node_t *par,ROMDISK_FILE_T *file){
	//dprintf("File base 0x%x 0x%x 0x%x",file,
	/* Allocate memory */
	vfs_node_t *node = (vfs_node_t *) kmalloc(sizeof(vfs_node_t));
	/* Clear memory */
	memset((void *)node,0,sizeof(vfs_node_t));
	/*Set up file node*/	
	strcpy(node->name,(char *)file->filename);
	node->gid = 0;
	node->uid = 0;
	node->mask = 0x1FF;
	node->flags = VFS_FILE_FLAG;
	node->parent = par;
	node->length = file->length;
	node->read = romfs_read;
	node->write = romfs_write;
	node->open = romfs_ocstub;
	node->close = romfs_ocstub;
	node->inode = (uint32_t)file;
	node->impl  = par->inode + (uint32_t)file->data;
	return node;
}

struct vfs_node * romfs_mount(struct vfs_node *special){
	ROMDISK_HEADER_T *hdr = (ROMDISK_HEADER_T *) special;
	/* Allocate memory */
	romfs_dir = (struct vfs_node *) kmalloc(sizeof(vfs_node_t));
	/* Clear memory */
	memset((void *)romfs_dir,0,sizeof(vfs_node_t));
	/* Set up romfs node */
	strcpy(romfs_dir->name,(char *)hdr->volname);
	romfs_dir->gid = 0;//Kernel is always root
	romfs_dir->uid = 0;// ^
	romfs_dir->mask = 0;
	romfs_dir->flags = VFS_DIRECTORY_FLAG;
	romfs_dir->parent = 0;
	romfs_dir->length = 0;
	romfs_dir->finddir = romfs_finddir;
	romfs_dir->readdir = romfs_readdir;
	romfs_dir->touch   = romfs_mkstub;
	romfs_dir->mkdir   = romfs_mkstub;
	romfs_dir->inode   = (uint32_t) hdr;
	return romfs_dir;
}

void romfs_umount(struct vfs_node *root){
	kfree((void *)root->inode);
}

void romfs_main(){
	romfs_dri_desc = (dri_driver_descriptor_t *) kmalloc(sizeof(dri_driver_descriptor_t));
	romfs_ifs_desc = (ifs_descriptor_t *) kmalloc(sizeof(ifs_descriptor_t));
	/* Set up IFS descriptor */
	strcpy(romfs_ifs_desc->ifs_name,"romfs");
	romfs_ifs_desc->ifs_id = 0x1337D15C;
	romfs_ifs_desc->ifs_mount_cb = romfs_mount;
	romfs_ifs_desc->ifs_umount_cb = romfs_umount;
	/* Set up DRI descriptor */
	strcpy(romfs_dri_desc->driver_name,"ROMDISK IFS Driver");
	romfs_dri_desc->driver_magic = DRI_DRIVER_MAGIC;
	romfs_dri_desc->driver_class = DRI_CLASS_IFS;
	romfs_dri_desc->driver_id    = romfs_ifs_desc->ifs_id;
	romfs_dri_desc->driver_class_desc = (void *) romfs_ifs_desc;
	romfs_dri_desc->init_sci = dri_syscall_initialize;
	romfs_dri_desc->driver_main = dri_driver_main_stub;
	/* Register driver with DRI */
	dri_register_driver(romfs_dri_desc);
}